package Network

import (
	"SQL/util"
	"fmt"
	"logs"
	"regexp"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

/*--------------------------类型转换---------------------------------------*/
func parseTime(timeStr string) (time.Time, bool) {

	strs := strings.Split(timeStr, "T")
	strs2 := strings.Split(strs[1], ".")

	var str3 string
	for key, value := range strs2[1] {
		if key >= 3 {
			break
		} else {
			str3 = str3 + string(value)
		}
	}

	str2 := strs[0] + " " + strs2[0] + "." + str3

	time, err := time.Parse("2006-01-02 15:04:05.000", str2)
	if err != nil {
		logs.Print("From:parseTime:---", err.Error())
		return time, false
	}
	return time, true
}

/*--------------------------基本checkout---------------------------------------*/
func checkOutId(id string) (bool, int, string) {

	info := "success"
	code := Success

	if id == "" {
		info = "From:checkOutId:--- id is invalid because id is null"
		return false, errInvalidID, info
	}

	//判断字符是否合法
	reg := regexp.MustCompile("^[1-9][0-9]{8}$")
	ok := reg.MatchString(id)
	if !ok {
		info = "From:checkOutId:---id is invalid"
		return false, errInvalidID, info
	}

	return true, code, info

}
func checkOutJsonInfo(jsonInfo string) (bool, int, string) {

	if jsonInfo == "" || jsonInfo == " " {
		return true, Success, "success"
	}
	//判断字符是否合法
	reg := regexp.MustCompile("^{.*(\\r*\\n*.*)*}$")
	ok := reg.MatchString(jsonInfo)
	if !ok {
		info := "From:checkOutJsonInfo:---jsonInfo is invalid"
		return false, errInvalidCustomInfo, info
	}
	return true, Success, "success"
}
func checkOutNickName(nickName string) (bool, int, string) {
	length := utf8.RuneCountInString(nickName)
	if length > 18 {
		info := "From:checkOutNickName:--- nickName is invalid because nickname is too long"
		return false, errInvalidNickname, info
	}
	if length <= 0 {
		info := "From:checkOutNickName:--- nickName is invalid because nickname is null"
		return false, errInvalidNickname, info
	}

	return true, Success, "success"
}

func checkOutIcon(icon string) (bool, int, string) {
	info := "success"
	code := Success
	ok := true

	l := len(icon)
	if l > 0 && l < 50 {
		return ok, code, info
	}

	info = "From:checkOutIcon:---icon is invalid"
	code = errInvalidIcon
	ok = false
	return ok, code, info
}

func checkOutPassword(password string) (bool, int, string) {
	length := utf8.RuneCountInString(password)
	//判断密码长度是否过长
	if length > 20 || length < 6 {
		info := "From:checkOutPassword:--- password is invalid because is too long or too short"
		return false, errPasswordWrong, info
	}

	//判断字符是否合法
	reg := regexp.MustCompile("^[\\da-zA-Z-_\\.\\?\\!\\,\\@\\#\\$\\%\\^\\&\\*\\(\\)\\=\\+\\[\\]\\{\\}]{6,20}$")
	ok := reg.MatchString(password)
	if !ok {
		info := "From:checkOutPassword:--- password is invalid because exist illegal char"
		return false, errPasswordWrong, info
	}

	return true, Success, "success"
}
func checkOutTime(createTime string) (bool, int, string) {
	_, err := time.Parse("2006-01-02 15:04:05", createTime)
	if err != nil {
		info := "From:checkOutTime:--- time is invalid---" + err.Error()
		return false, errInvalidTime, info
	}
	return true, Success, "success"
}
func checkOutPageIndex(pageIndex string) (bool, int, string) {
	reg := regexp.MustCompile("^0[1-9]${1}|^[1-9][0-9]$|^0$|^[1-9]$")
	ok := reg.MatchString(pageIndex)
	if !ok {
		info := "From:checkOutPageIndex:--- pageIndex is invalid"
		return ok, errInvalidPageIndex, info
	}
	value, err := strconv.Atoi(pageIndex)
	if err != nil {
		logs.Print("From:checkOutPageIndex:---", err.Error())
		info := "From:checkOutPageIndex:--- pageIndex is invalid"
		return false, errInvalidPageIndex, info
	}
	if value < 0 || value > 999999 {
		logs.Print("From:checkOutPageIndex:---", err.Error())
		info := "From:checkOutPageIndex:--- pageIndex is invalid because too large or too small"
		return false, errInvalidPageIndex, info
	}
	return true, Success, "success"
}
func checkOutPageSize(pageSize string) (bool, int, string) {

	reg := regexp.MustCompile("^0[1-9]${1}|^[1-9][0-9]$|^0$|^[1-9]$")
	ok := reg.MatchString(pageSize)
	if !ok {
		info := "From:checkOutPageSize:--- pageSize is invalid"
		return ok, errInvalidPageIndex, info
	}

	value, err := strconv.Atoi(pageSize)
	if err != nil {
		info := "From:checkOutPageSize:--- pageSize is invalid"
		return false, errInvalidPageIndex, info
	}
	if value < 0 || value > 999 {
		info := "From:checkOutPageSize:--- pageSize is invalid because too large or too small"
		return false, errInvalidPageIndex, info
	}
	return true, Success, "success"
}
func checkOutAccount(account string) (ok bool, code int, info string) {
	info = "success"
	code = Success
	ok = true
	reg := regexp.MustCompile("^[0-9]{11}$")
	ok = reg.MatchString(account)
	if !ok {
		info = "From:checkOutId:---id is invalid"
		return false, errInvalidAccount, info
	}

	return ok, code, info
}

/*--------------------------基本判定---------------------------------------*/
func isGroupMember(userID string, groupID string) (string, int, bool) {
	info := "success"
	code := Success
	ok := true

	ok, code, info = checkOutId(userID)
	if !ok {
		info = "From:isGroup---userID is invalid"
		return info, code, ok
	}
	ok, code, info = checkOutId(groupID)
	if !ok {
		info = "From:isGroup---groupID is invalid"
		return info, code, ok
	}

	info, code, ok = isGroup(groupID)
	if !ok {
		info = "From:isGroupMember.isGroup---isGroup is invalid because groupID is not group"
		return info, code, ok
	}

	info, code, ok = isUser(userID)
	if !ok {
		info = "From:isGroupMember.isUser---userID is invalid because userID is not user"
		return info, code, ok
	}

	sql := "select userid from members where groupid = $1"
	rows, stmt, err := util.Query(sql, groupID)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}
	if err != nil {
		if err != nil {
			logs.Print("From:isGroupMember.Query:---", err.Error())
			info = "From:isGroupMember.Query:---error"
			return info, errDBQueryFailed, false
		}
	}

	var memberID string
	for rows.Next() {
		err = rows.Scan(&memberID)
		if err != nil {
			logs.Print("From:isGroupMember.Scan:---", err.Error())
			info = "From:isGroupMember.Scan:---error"
			return info, errRowsScan, false
		}
		if memberID == userID {
			return info, code, true
		}
	}
	info = "From:isGroupMember.Scan:---userID is not the talkerID group member"
	return info, errInvalidID, false
}
func isGroup(id string) (string, int, bool) {
	info := "success"
	code := Success
	ok := true

	ok, code, info = checkOutId(id)
	if !ok {
		info = "From:isGroup---id is invalid"
		return info, code, ok
	}

	sql := "select isuser from objects where id = $1"

	rows, stmt, err := util.Query(sql, id)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}
	if err != nil {
		if err != nil {
			logs.Print("From:isGroup.Query", err.Error())
			info = "From:isGroup.Query---error"
			return info, errDBQueryFailed, false
		}
	}
	var isUser bool
	if rows.Next() {
		err = rows.Scan(&isUser)
		if err != nil {
			fmt.Println("From:isGroup.Scan", err.Error())
			info = "From:isGroup.Scan---error"
			return info, errRowsScan, false
		}
		if isUser {
			info = "From:isGroup:---id is invalid because id is not group"
			code = errInvalidID
			return info, code, false
		} else {
			return info, code, true
		}
	} else {
		info = "From:isGroup:---id is invalid because id is not object"
		code = errInvalidID
		return info, code, false

	}

	return info, code, true
}
func isObject(id string) (string, int, bool) {
	info := "success"
	code := Success
	ok := true

	ok, code, info = checkOutId(id)
	if !ok {
		info = "From:isObject:---id is invalid"
		return info, code, ok
	}
	sql := "select * from objects where id = $1"
	rows, stmt, err := util.Query(sql, id)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}
	if err != nil {
		logs.Print("From:alterObjectData.queryObject.Query:---", err.Error())
		info = "From:isObject.Query:---error"
		return info, errDBQueryFailed, false
	}

	if !rows.Next() {
		info = "From:isObject:---objectID is invalid because the objectID is no exist"
		return info, errInvalidID, false
	}

	return info, Success, true
}
func isOwner(ownerID string, gourpID string) (string, int, bool) {

	info := "success"
	code := Success
	ok := true

	ownerParam, err := strconv.ParseInt(ownerID, 10, 64)
	if err != nil {
		info = "From:isOwner.ParseInt:---ownerID is invalid"
		code = errInvalidID
		ok = false
		return info, code, ok

	}

	ok, code, info = checkOutId(ownerID)
	if !ok {
		info = "From:isOwner:---id is invalid"
		return info, code, ok
	}
	ok, code, info = checkOutId(gourpID)
	if !ok {
		info = "From:isOwner:---id is invalid"
		return info, code, ok
	}

	sql := "select owner from groups where id =$1"
	rows, stmt, err := util.Query(sql, gourpID)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}

	if err != nil {
		info = "From:isOwner.rows.Query:---error"
		return info, errDBQueryFailed, false
	}
	var owner int64
	if !rows.Next() {
		info = "From:isOwner.rows.Next:---id is invalid because id is not user"
		return info, errInvalidID, false
	}
	err = rows.Scan(&owner)

	if owner != ownerParam {
		info = "From:isOwner.rows.Next:---id is invalid because id is not a managerID"
		return info, errInvalidID, false
	}
	return info, Success, true
}
func isUser(id string) (string, int, bool) {
	info := "success"
	code := Success
	ok := true

	ok, code, info = checkOutId(id)
	if !ok {
		info = "From:isUser:---id is invalid"
		return info, code, ok
	}

	sql := "select isuser from objects where id = $1"

	rows, stmt, err := util.Query(sql, id)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}

	if err != nil {
		if err != nil {
			logs.Print("From:isUser.Query", err.Error())
			info = "From:isUser.Query:---error"
			return info, errDBQueryFailed, false
		}
	}
	var isUser bool
	if rows.Next() {
		err = rows.Scan(&isUser)
		if err != nil {
			logs.Print("From:isUser.Scan", err.Error())
			info = "From:isUser.Scan:---error"
			return info, errRowsScan, false
		}
		if isUser {
			return info, code, true
		} else {
			info = "From:isUser:---id is invalid because id is not user"
			code = errInvalidID
			return info, code, false
		}
	} else {
		info = "From:isUser:---id is invalid because id is not object"
		code = errInvalidID
		return info, code, false

	}

	return info, code, true
}
func isAccountExist(account string) (info string, code int, ok bool) {
	info = "success"
	code = Success
	ok = true

	sql := "select * from users where account = $1"
	rows, stmt, err := util.Query(sql, account)
	if stmt != nil {
		defer stmt.Close()
	}
	if rows != nil {
		defer rows.Close()
	}
	if err != nil {
		logs.Print("From:isAccountExist.Query", err.Error())
		info = "From:isAccountExist.Query:---error"
		return info, errDBQueryFailed, false
	}
	if !rows.Next() {
		info = "From:isAccountExist.rows.Next:---account is not exist"
		code = errInvalidAccount
		ok = false
		return
	}
	return
}
